package net.sxnic.ugr.menu;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;

import net.sxinfo.core.entity.AbstractEntity;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;

@Entity
@Table(name = "ugr_menu")
@BatchSize(size = 10)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Menu extends AbstractEntity {
	
	private static final long serialVersionUID = -3501373015915866523L;
	//可用
	public static final boolean ENABLED_STAUTUS = true;
	//不可用
	public static final boolean DISABLED_STAUTUS = false;

	//菜单的编码如一级01 二级0101、0102 三级010101、010102、010201、010202
	//如此编码方式便于多级菜单的定位
	@Column(nullable=false,unique=true)
	private String code;
	
	//菜单所显示的名字
	private String value;
	
	//与之对应的url
	private String url;
	
	//排序字段，查询的时候一般按menuOrder和code排序
	@Index(name="menu_order")
	private int menuOrder;
	
	//状态 默认为true
	private boolean status;
	
	private String imageurl;
	
	/**
	 * 所属子系统code ,如果未空表示公用，如果有值则表示子系统专用
	 */
	private String siteCode;
	
	private Integer priority;
	
	private Boolean treeLeaf;

	@ManyToOne(fetch = FetchType.LAZY)
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	private Menu parent;
	
	@ManyToMany(fetch=FetchType.LAZY)
	@OrderBy("code")
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	private Set<Menu> child;

	public Menu() {
		super();
		child = new LinkedHashSet<Menu>();
		status = true;
	}

	public Menu(String code, String value) {
		super();
		this.code = code;
		this.value = value;
		this.status = true;
	}
	
	/**
	 * 获得节点列表。从父节点到自身。
	 * 
	 * @return
	 */
	public List<Menu> getNodeList() {
		LinkedList<Menu> list = new LinkedList<Menu>();
		Menu node = this;
		while (node != null) {
			list.addFirst(node);
			node = node.getParent();
		}
		return list;
	}

	/**
	 * 获得节点列表ID。从父节点到自身。
	 * 
	 * @return
	 */
	public String[] getNodeIds() {
		List<Menu> menus = getNodeList();
		String[] ids = new String[menus.size()];
		int i = 0;
		for (Menu c : menus) {
			ids[i++] = c.getId();
		}
		return ids;
	}

	/**
	 * 获得深度
	 * 
	 * @return 第一层为0，第二层为1，以此类推。
	 */
	public int getDeep() {
		int deep = 0;
		Menu parent = getParent();
		while (parent != null) {
			deep++;
			parent = parent.getParent();
		}
		return deep;
	}
	
	/**
	 * @see HibernateTree#getParentId()
	 */
	public String getParentId() {
		Menu parent = getParent();
		if (parent != null) {
			return parent.getId();
		} else {
			return null;
		}
	}

	public static String[] fetchIds(Collection<Menu> menus) {
		if (menus == null) {
			return null;
		}
		String[] ids = new String[menus.size()];
		int i = 0;
		for (Menu c : menus) {
			ids[i++] = c.getId();
		}
		return ids;
	}
	
	public boolean isTreeLeaf() {
		if (treeLeaf != null) {
			return treeLeaf;
		}
		Set<Menu> child = getChild();
		if (child != null && child.size() > 0) {
			return false;
		} else {
			return true;
		}
	}


	public String getCode() {
		return this.code;
	}

	public String getValue() {
		return this.value;
	}

	public String getUrl() {
		return this.url;
	}

	 
	
	public void setCode(String code) {
		this.code = code;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	 
	 
	 
	public int getMenuOrder() {
		return menuOrder;
	}

	public void setMenuOrder(int menuOrder) {
		this.menuOrder = menuOrder;
	}

	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	public String getImageurl() {
		return imageurl;
	}

	public void setImageurl(String imageurl) {
		this.imageurl = imageurl;
	}

	public Integer getPriority() {
		return priority;
	}

	public void setPriority(Integer priority) {
		this.priority = priority;
	}

	public Boolean getTreeLeaf() {
		return treeLeaf;
	}

	public void setTreeLeaf(Boolean treeLeaf) {
		this.treeLeaf = treeLeaf;
	}
	
	
	public Menu getParent() {
		return parent;
	}

	public void setParent(Menu parent) {
		this.parent = parent;
	}

	public Set<Menu> getChild() {
		return child;
	}

	public void setChild(Set<Menu> child) {
		this.child = child;
	}

	public String getSiteCode() {
		return siteCode;
	}

	public void setSiteCode(String siteCode) {
		this.siteCode = siteCode;
	}

	
}
